﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace NPipeline.Driver
{
    public abstract class BaseStageDriver
    {
        protected IStage stage;

        protected IStageContext context;

        protected volatile PipelineState currentState = PipelineState.STOPPED;

        // there should be something about the faultTolerance


        // Collections to remember the processing errors
        protected List<ProcessingException> processingExceptions = new List<ProcessingException>();

        protected List<Exception> errors = new List<Exception>();

        // FaultTolerance handling is missing
        public BaseStageDriver(IStage stage, IStageContext context)
        {
            // check the parameters ...
            this.stage = stage;
            this.context = context;
        }

        /// <summary>
        /// Atomicly check if the Driver is in a specific state
        /// </summary>
        /// <param name="states"></param>
        /// <returns></returns>
        protected bool isInState(PipelineState[] states)
        {
            lock (this)
            {
                foreach (PipelineState check in states)
                {
                    if (currentState == check) return true;
                }
                return false;
            }
        }

        protected void SetState(PipelineState nextState)
        {
            lock (this)
            {
                currentState = nextState;
                // we would need the events here 
                // this.notifyAll()
            }

        }

        protected bool TestAndSetState(PipelineState testState, PipelineState nextState)
        {
            lock (this)
            {
                if (currentState == testState)
                {
                    SetState(nextState);
                    return true;
                }
                else
                {
                    return false;
                }
            }


        }


        protected void recordFatalError(Exception error)
        {
            this.errors.Add(error);
        }

        protected void recordProcessingException(object data, Exception error)
        {
            // TODO - processing Exception needs to be able to take a Exception as a parameter
            // just taking the currentState MAY not be thread safe ??
            ProcessingException ex = new ProcessingException(this.stage, "NOT DONE YET", data, currentState);
            this.processingExceptions.Add(ex);
        }


        public PipelineState CurrentState { get { return currentState; } }


        #region IStageDriver Members

        public IStage Stage
        {
            get { return stage; }
        }

        public List<Exception> FatalErrors
        {
            get { return errors; }
        }

        public List<ProcessingException> ProcessingExceptions
        {
            get { return processingExceptions;  }
        }

        #endregion
    }
}
